package server

import (
  "fmt"
  "net/http"
  "strconv"
  "strings"

  "encoding/json"

  "github.com/siddontang/go-log/log"
)

const (
  API_URL_REGISTER = "api/member/register.json"
)

var (
  respOK = []byte(`{"success":1}`)
)

type httpClient struct {
  app *App

  resp responseWriter
  req  *requestContext
}

type httpWriter struct {
  cmd string
  w   http.ResponseWriter
}

func newClientHTTP(app *App, w http.ResponseWriter, r *http.Request) {
  var err error
  c := new(httpClient)
  c.app = app

  c.req, err = c.makeRequest(app, r, w)
  if err != nil {
    w.Write([]byte(err.Error()))
    return
  }
  c.req.perform()
}

func (c *httpClient) addr(r *http.Request) string {
  return r.RemoteAddr
}

func (c *httpClient) makeRequest(app *App, r *http.Request, w http.ResponseWriter) (*requestContext, error) {
  cmd, argsStr, err := c.parseRequest(r)
  if err != nil {
    return nil, err
  }

  req := newRequestContext(app)
  args := make([][]byte, len(argsStr))
  for i, arg := range argsStr {
    args[i] = []byte(arg)
  }

  req.cmd = strings.ToLower(cmd)
  req.args = args
  req.remoteAddr = c.addr(r)
  req.resp = &httpWriter{cmd, w}
  return req, nil
}

func (c *httpClient) parseRequest(r *http.Request) (cmd string, args []string, err error) {
  substrings := strings.Split(strings.TrimLeft(r.URL.Path, "/"), "/")
  if len(substrings) != 3 {
    return "", nil, fmt.Errorf("invalid request url %s", r.URL.Path)
  }

  cmd = substrings[1]
  args = make([]string, 5)
  args[0] = substrings[2]

  // parse form data
  err = r.ParseForm()
  if err != nil {
    return "", nil, err
  }

  args[1] = r.FormValue("user")
  args[2] = r.FormValue("familyname")
  args[3] = r.FormValue("email")
  args[4] = r.FormValue("password")

  return
}

// http writer
func (w *httpWriter) writeError(err error) {
  result := make(map[string]interface{}, 3)
  result["success"] = 0
  result["errcode"] = 0
  result["errmsg"] = err.Error()

  b, err := json.Marshal(result)
  if err != nil {
    log.Error(err.Error())
    return
  }
  writeJSON(b, w.w)
}

func (w *httpWriter) writeBulk(b []byte) {
  writeJSON(b, w.w)
}

func (w *httpWriter) flush() {}

func writeJSON(buf []byte, w http.ResponseWriter) {
  w.Header().Set("Content-type", "application/json; charset=utf-8")
  w.Header().Set("Content-Length", strconv.Itoa(len(buf)))
  _, err := w.Write(buf)
  if err != nil {
    log.Error(err.Error())
  }
}
